/*
LICENCIA
========
Copyright (C) 2009

Autores:

Carlos Alberto Martínez Gadea   <camg6@alu.ua.es>
Manel Simon Martínez            <msm85@alu.ua.es>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "util.h"

using namespace std;

//Función encargada de mostrar la tabla de las particiones por terminal
void MostrarTabla(const TLista& l, ofstream& salida)
{
    /* Muestra la lista tras acabar con el fichero de comandos */
    TListaNodo* aux = l.GetCabeza();
    string format;

    salida << "Tabla de particiones\n\n";
    salida << "Nº\tPROG\tESTADO\tREG. BASE\tTAMAÑO\n";

    while(aux != NULL)
    {
        salida << aux -> GetId()
        << "\t" << aux -> GetProg()
        << "\t" << aux -> Asignado()
        << "\t" << aux -> GetRegBase()
        << "\t\t" << aux -> GetRegLim()
        << "\n";

        aux = aux -> GetSig();
    }
}

//Func. auxiliar que extrae el Tamaño del Programa del string entrada
int ParseaTamProg(string entrada)
{
    string programa;
    int i;

    for(i=2; i < entrada.length() && entrada[i] != ' ';i++)
    {
        programa += entrada[i];
    }

    return atoi(&entrada[i]);
}

//Func. auxiliar que extrae el Nombre del Programa del string entrada
string ParseaNomProg(string entrada)
{
    string programa;
    int i;

    for(i=2; i < entrada.length() && entrada[i] != ' ';i++)
    {
        programa += entrada[i];
    }

    return programa;
}

/*Func. principal de la aplicación la cual se encargará de leer el fichero de
 * entrada y de procesar cada una de las instrucciones que en él se encuentren,
 * produciendo un fichero de salida asociado al mismo */
void FileRead(char* name)
{
    TLista particiones;                 /* Tabla de particiones (lista) */

    // Declaración de ficheros
    ifstream file;                      /* Fichero de entrada */
    ofstream output;                    /* Fichero de salida */

    // Declaración y asignación del nombre del fichero de salida
    char fout[strlen(name)];
    strcpy(fout, name);                 /* Copia del nombre de fichero de entrada */

    fout[strlen(fout) - 3] = 's';
    fout[strlen(fout) - 2] = 'a';
    fout[strlen(fout) - 1] = 'l';

    // Apertura de ficheros
    file.open(name, ios::in);
    output.open(fout, ios::out);

    string cad;

    if(file && output)
    {
        // El fichero se ha abierto correctamente (y existe)
        getline(file, cad);

        while(!file.eof())
        {
            switch(cad[0])
            {
                case 'R':                           /* Reservar espacio  COMANDO R*/
                    particiones.ReservarEspacio(cad,output);
                    break;

                case 'r':                           /* Reservar con compactación  COMANDO r*/
                    particiones.ReservaYCompacta(cad, output);
                    break;

                case 'L':                           /* Libera la partición de la lista COMANDO L*/
                    particiones.LiberarParticion(ParseaNomProg(cad));
                    output << kLIBERA << ParseaNomProg(cad) << endl;
                    break;

                case 'A':                           /* Activar algoritmo  COMANDO A*/
                    particiones.SetAlgoritmo(&cad[2],output);
                    break;

                case 'D':                           /* Direcciones relativas  COMANDO D*/
                    particiones.AccederDireccion(ParseaNomProg(cad), ParseaTamProg(cad), output);
                    break;

                case 'C':                           /* Compactar  COMANDO C*/
                    particiones.Compacta();
                    output << kC;
                    break;

                case 'T':                           /* Mostrar la tabla  COMANDO T*/
                    MostrarTabla(particiones, output);
                    break;

                case 'F': output << kFIN;           /* Finaliza la simulación y escribe en el fichero de salida COMANDO F */
                    break;

                case 'M':                           /* Ampliación de la partición COMANDO M*/
                   particiones. AmpliarParticion(cad,output);
                    break;

                default:
                    break;
            }

            getline(file, cad);
        }
    }
    else
    {
        cerr << "gmpd: file '" << name << "' does not exists\n";
    }

    file.close();
    output.close();
}
